package cn.edu.scut.hsrc.bean;

import java.util.ArrayList;
import java.util.List;

import cn.edu.scut.hsrc.bean.Word.RelationToQuery;
import cn.edu.scut.hsrc.bean.WordType.Type;

/**
 * 这个类词的集合，每个词都是唯一出现的
 * @file DocWords.java
 * @author feiyu
 *
 */

public class WordSet {
	private List<RefWord> words;	//词的集合（每个词都是单一的，这个集合不可能出现两个相同的词）
	private List<Integer> weight;	//词在文档中的权重
	
	//在标题中出现一次权重为2，在summary中出现权重为1
	private final static int WEIGHT_IN_TITLE = 2;
	private final static int WEIGHT_IN_SUMMARY = 1;
	
	public enum TS{TITLE,SUMMARY};	//词在title还是在summary中
	
	/**
	 * 
	 * 构造函数
	 */
	public WordSet() {
		// TODO Auto-generated constructor stub
		this.words = new ArrayList<RefWord>();
		this.weight = new ArrayList<Integer>();
	}
	
	/**
	 * 返回词的集合
	 * @return
	 */
	public List<RefWord> getWords()
	{
		return this.words;
	}
	
	/**
	 * 获取一个词在该文档中的权重
	 * @param index 词的下标
	 * @return
	 */
	public int getWeight(int index)
	{
		return this.weight.get(index);
	}
	
	/**
	 * 添加词，这里会进行去重处理
	 * @param word	词
	 * @param where 词出现在title或summary中
	 */
	public void addWord(RefWord word,TS where)
	{
		int index = this.words.indexOf(word);
		if(index < 0)
		{
			this.words.add(word);
			if(where == TS.TITLE)
				this.weight.add(WEIGHT_IN_TITLE);
			else if(where == TS.SUMMARY)
				this.weight.add(WEIGHT_IN_SUMMARY);
		}else {
			//如果已经存在了，就增加它的权重，并且合并反引用
			int weight = this.weight.get(index);
			if(where == TS.TITLE)
				weight += WEIGHT_IN_TITLE;
			else if(where == TS.SUMMARY)
				weight += WEIGHT_IN_SUMMARY;
			this.weight.set(index, weight);
			//合并反引用
			this.words.get(index).addRefs(word.getRefs());
		}
	}
	
	/**
	 * 把词加入集合中，这里会进行去重处理
	 * @param word 词
	 * @param weight 词权重
	 */
	public void addWord(RefWord word,int weight)
	{
		int index = this.words.indexOf(word);
		if(index < 0)
		{
			this.words.add(word);
			this.weight.add(weight);
		}else {
			//如果已经存在了，就增加它的权重，并且合并反引用
			this.weight.set(index, this.weight.get(index)+weight);
			this.words.get(index).addRefs(word.getRefs());
		}
	}
	
	/**
	 * 对文档中的词，按照它们的权重进行排序，权重最高的排最前面，选择插入排序
	 */
	public void sort() {
		int size = this.words.size();
		for(int i=0;i<size;i++)
		{
			int maxWeight = this.weight.get(i);
			int maxIndex = i;
			for(int j=i+1;j<size;j++)
			{
				if(this.weight.get(j) > maxWeight)
				{
					maxWeight = this.weight.get(j);
					maxIndex = j;
				}
			}
			//对maxIndex和i位置的元素进行交换
			if(maxIndex != i)
			{
				RefWord tmpWord = this.words.get(maxIndex);
				int tmpWeight = this.weight.get(maxIndex);
				this.words.set(maxIndex, this.words.get(i));
				this.weight.set(maxIndex, this.weight.get(i));
				this.words.set(i, tmpWord);
				this.weight.set(i, tmpWeight);
			}
		}
	}
	
	/**
	 * 返回下标为index对应词和权重
	 * @param index
	 * @return 如果不越界，返回<词，权重>，否则返回null
	 */
	public Pair<RefWord, Integer> getWordAndWeight(int index)
	{
		if(index >= this.words.size())
			return null;
		return new Pair<RefWord, Integer>(this.words.get(index),this.weight.get(index));
	}
	
	/**
	 * 返回下标为index对应的词
	 * @param index
	 * @return 如果不越界，返回对应的词，否则返回null
	 */
	public RefWord getWord(int index) {
		if(index >= this.words.size())
			return null;
		return this.words.get(index);
	}
	
	/**
	 * 返回字符串是str的词
	 * @param str
	 * @return 如果存在就返回那个词，如果不存在就返回null
	 */
	public RefWord getWord(String str) {
		int index = indexOf(str);
		if(index == -1)
			return null;
		else return this.words.get(index);
	}

	/**
	 * 返回词的总个数
	 * @return
	 */
	public int count()
	{
		return this.words.size();
	}
	
	/**
	 * 返回词word在集合中的下标位置，没有则返回-1
	 * @param word
	 * @return
	 */
	public int indexOf(RefWord word)
	{
		if(word == null)
			return -1;
		return this.words.indexOf(word);
	}
	
	/**
	 * 返回字符串str在集合中的下标位置，没有则返回-1
	 * @param str
	 * @return
	 */
	public int indexOf(String str)
	{
		if(str == null)
			return -1;
		return this.words.indexOf(new RefWord(str, Type.OTHER,RelationToQuery.NOTHING,-1,-1));
	}

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		String text = "";
		int size = this.words.size();
		for(int i=0;i<size;i++)
		{
			text += this.words.get(i).getText()+":"+this.weight.get(i)+" | ";
		}
		if(text.length() > 0)
			text = text.substring(0,text.length()-3);
		text += "\n";
		return text;
	}
}

